package org.example.service.authorization.client;

import lombok.Data;
import org.example.bean.entity.authorization.Client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@Service
public class CustomClientDetailsService implements ClientDetailsService {
    private IClientService service;

    @Autowired
    public CustomClientDetailsService(IClientService service) {
        this.service = service;
    }

    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
        Client client = service.findByClientId(clientId);
        if (client != null) {
            ClientDetails details = new ClientDetailsImpl(client);
            return details;
        } else {
            return null;
        }
    }

    @Data
    public static class ClientDetailsImpl implements ClientDetails {
        private Client client;

        public ClientDetailsImpl(Client client) {
            this.client = client;
        }

        @Override
        public String getClientId() {
            return client.getClientId();
        }

        @Override
        public Set<String> getResourceIds() {
            if (client.getResourceIds() != null && client.getResourceIds().length > 0) {
                Set<String> data = new HashSet<>();
                for (String item : client.getResourceIds()) {
                    data.add(item);
                }
                return data;
            }
            return null;
        }

        @Override
        public boolean isSecretRequired() {
            return true;
        }

        @Override
        public String getClientSecret() {
            return client.getClientSecret();
        }

        @Override
        public boolean isScoped() {
            return client.getScope() != null && client.getScope().length > 0;
        }

        @Override
        public Set<String> getScope() {
            if (client.getScope() != null && client.getScope().length > 0) {
                Set<String> data = new HashSet<>();
                for (String item : client.getScope()) {
                    data.add(item);
                }
                return data;
            }
            return null;
        }

        @Override
        public Set<String> getAuthorizedGrantTypes() {
            if (client.getAuthorizedGrantTypes() != null && client.getAuthorizedGrantTypes().length > 0) {
                Set<String> data = new HashSet<>();
                for (String item : client.getAuthorizedGrantTypes()) {
                    data.add(item);
                }
                return data;
            }
            return null;
        }

        @Override
        public Set<String> getRegisteredRedirectUri() {
            if (client.getRedirectUris() != null && client.getRedirectUris().length > 0) {
                Set<String> data = new HashSet<>();
                for (String item : client.getRedirectUris()) {
                    data.add(item);
                }
                return data;
            }
            return null;
        }

        @Override
        public Collection<GrantedAuthority> getAuthorities() {
            if (client.getAuthorities() != null && client.getAuthorities().length > 0) {
                Set<GrantedAuthority> data = new HashSet<>();
                for (String item : client.getAuthorities()) {
                    data.add(new SimpleGrantedAuthority(item));
                }
                return data;
            }
            return null;
        }

        @Override
        public Integer getAccessTokenValiditySeconds() {
            return client.getAccessTokenValiditySeconds();
        }

        @Override
        public Integer getRefreshTokenValiditySeconds() {
            return getClient().getRefreshTokenValiditySeconds();
        }

        @Override
        public boolean isAutoApprove(String s) {
            return getClient().getAutoApprove();
        }

        @Override
        public Map<String, Object> getAdditionalInformation() {
            return null;
        }
    }


}
